import json
from decimal import Decimal

from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection
from django.utils import timezone
from apps.goods.models import SKU
from utils.views import LoginRequiredJsonMixin
from apps.users.models import Address
from apps.orders.models import OrderInfo, OrderGoods
from django.db import transaction


class OrderSettlementView(LoginRequiredJsonMixin, View):
    def get(self, request):
        """结算订单"""
        user = request.user
        # # 地址信息 # #
        addresses_queryset = Address.objects.filter(user_id=user.id, is_deleted=False)
        addresses = [{
            'id': address.id,
            'title': address.title,
            'receiver': address.receiver,
            'province': address.province.name,
            'city': address.city.name,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email,
            'default_address_id': user.default_address_id
        } for address in addresses_queryset]
        # # 选中订单信息 # #
        redis_cli = get_redis_connection('carts')
        redis_pl = redis_cli.pipeline()
        redis_pl.hgetall('carts_%s' % user.id)
        redis_pl.smembers('selected_%s' % user.id)
        result = redis_pl.execute()
        skus = []
        for sku_id in result[1]:
            sku = SKU.objects.get(id=int(sku_id))
            skus.append({
                'id': int(sku_id),
                'name': sku.name,
                'count': int(result[0].get(sku_id)),
                'default_image_url': sku.default_image.url,
                'price': sku.price,
            })
        # 补充运费
        freight = Decimal('10.00')
        context = {
            'skus': skus,
            'freight': freight,
            'addresses': addresses,
        }
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'context': context})


class OrderCommitView(LoginRequiredJsonMixin, View):
    def post(self, request):
        # 1、获取前端数据
        user = request.user
        data_dict = json.loads(request.body.decode())
        address_id = data_dict.get('address_id')
        pay_method = data_dict.get('pay_method')
        # 2、校验数据
        if not all([address_id,  pay_method]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})
        try:
            Address.objects.get(id=address_id)
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '参数address_id错误'})
        if pay_method not in (OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']):
            return JsonResponse({'code': 400, 'errmsg': '支付方式有误'})
        # 3、保存数据
        # 订单基本信息
        order_id = timezone.now().strftime('%Y%m%d%H%M%S%f') + '%09d' % user.id
        # order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)
        total_count = 0
        total_amount = Decimal('0')
        freight = Decimal('10.00')
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']
        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address_id=address_id,
                    total_count=total_count,
                    total_amount=total_amount,
                    freight=freight,
                    pay_method=pay_method,
                    status=status
                )
                # 订单商品信息
                redis_cli = get_redis_connection('carts')
                redis_pl = redis_cli.pipeline()
                redis_pl.hgetall('carts_%s' % user.id)
                redis_pl.smembers('selected_%s' % user.id)
                result = redis_pl.execute()
                sku_id_count, is_selected = result
                carts = {}
                for sku_id in is_selected:
                    carts[int(sku_id)] = int(sku_id_count[sku_id])
                for sku_id, count in carts.items():
                    while True:
                        sku = SKU.objects.get(id=sku_id)
                        if sku.stock < count:
                            transaction.savepoint_rollback(save_point)
                            return JsonResponse({'code': 400, 'errmsg': '商品库存不足'})
                        # sku.stock -= count
                        # sku.sales += count
                        # sku.save()
                        # 乐观锁   解决超卖问题
                        # 读取原始库存
                        # import time
                        # time.sleep(4)
                        origin_stock = sku.stock
                        origin_sales = sku.sales
                        # 乐观锁更新库存和销量
                        new_stock = origin_stock - count
                        new_sales = origin_sales + count
                        result = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock, sales=new_sales)
                        if result == 0:
                            continue
                            # transaction.savepoint_rollback(save_point)
                            # return JsonResponse({'code': 400, 'errmsg': '下单失败'})
                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            count=count,
                            price=sku.price,
                        )
                        order.total_count += count
                        order.total_amount += count * sku.price
                        break
                order.save()
            except Exception as e:
                transaction.savepoint_rollback(save_point)
                return JsonResponse({'code': 400, 'errmsg': '数据保存失败'})
            transaction.savepoint_commit(save_point)
        # Todo 删除Redis数据
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'order_id': order_id})



